#include <GL/glut.h>
#include <stdexcept>
#include <iostream>
#include <memory>
#include "game.hpp"



//поскольку по условиям, нормальными библиотеками пользоваться низя
//мы будет использовать страшную херню из 1980х под названием GLUT
//GLUT наглухо прибит гвоздями к статическим переменным, поэтому 
//класс нашей игры будет сидеть в глобальной переменной

//в этом файле все настолько тупо и прямо делается, что я даже 
//не знаю что сюда написать. тут надо что-то менять если GLUT 
//не будет нас устраивать
static game * agame(0);
bool mouse_enter(true);//а вот эта переменная подпирает косяк glut
//с входом курсора в окно.
static void onMouse(int button, int state, int x, int y) throw ()
{
	if(mouse_enter){
		agame->mouse_enter(x,y);
		mouse_enter=false;
	}else{
		agame->mouse_click(button, state==GLUT_DOWN, x, y);
	}
}
static void onMouseMotion(int x, int y) throw ()
{
	if(mouse_enter){
		agame->mouse_enter(x,y);
		mouse_enter=false;
	}else{
		agame->mouse_motion(x, y);
	}
}
static void onMouseEnter(int state) throw ()
{
	if(state==GLUT_ENTERED)
		mouse_enter=true;
}

static void onReshape(int w, int h) throw ()
{
	//это для изменения размеров окна
	agame->resize(w, h);
	glViewport(0,0,w,h);	
	glutPostRedisplay();
}
static void onDisplay() throw ()
{
	//а тут перерисовка собственно
	agame->paint();
	glFinish();
	glutSwapBuffers();
	//обновим сцену после каждого кадра
	agame->update_scene();
	//и так вечно
	glutPostRedisplay();
}
int main(int argc, char ** argv)
{
	try{
		//инициализуем GLUT
		glutInit(&argc, argv);
		glutInitDisplayMode(GLUT_RGB | GLUT_ALPHA | GLUT_DEPTH | GLUT_DOUBLE);
		//создадим окно, и если оно создалось, настроим там все
		int windowid=glutCreateWindow("Test");
		if(windowid)
		{
			//установим обработчики
			glutReshapeFunc(onReshape);
			glutDisplayFunc(onDisplay);
			glutMouseFunc(onMouse);
			glutEntryFunc(onMouseEnter);
			glutMotionFunc(onMouseMotion);
			glutPassiveMotionFunc(onMouseMotion);
			//создадим игру в главном потоке где контекст GL и зададим размер
			std::auto_ptr<falling_things> game_class(new falling_things(640,480));
			{
				std::auto_ptr<game> wrapper_class(new game(640,480, game_class.get()));
				agame=wrapper_class.get();
				glutReshapeWindow(640,480);
				//главный цикл
				glutMainLoop();
			}
		}
	}catch(std::exception& ex){
		std::cerr<<"FATAL ERROR: "<<ex.what()<<std::endl;
		exit(1);
	}catch(...){
		std::cerr<<"FATAL ERROR: "<<"unknown error"<<std::endl;
		exit(1);
	}
	return 0;
}
